'''
Created on 08/12/2009

@author: eh01
'''
from Queue import Queue
from datastore import database
from datastore.resource import Resource
from runtime import rt
from runtime.spaces import Spaces, SpacesContext
from services.httpclienttask import HTTPClientTask
from services.updatemanagertask import UpdateManagerTask
from datastore.database import DataStore, NotFoundException
import base64
import logging
import os
import time
import unittest

LOGGING = logging.DEBUG

class UpdateManagerTaskTest(unittest.TestCase):

    def setUp(self):
        queue = Queue()
        self.spaces = Spaces()
        spaces_context = SpacesContext(self.spaces, queue)
        runtime = rt.Runtime()
        runtime.initialise_spaces_with_local_config_files(spaces_context)

        self.temp_database_name = 'test.db'
        self.original_database_name = database.DATABASE_NAME
        database.DATABASE_NAME = self.temp_database_name        


    def tearDown(self):
        try:
            os.remove(self.temp_database_name)
        except:
            pass


    def test_install_new_package(self):
        '''test install new package'''
        # we'll use files in the current directory as the "packages"
        package_1_loc = os.path.dirname(__file__) + '/updatemanagertask.py'
        package_2_loc = os.path.dirname(__file__) + '/configuration.xml'
        ds = DataStore(self.spaces.ns)
        queue = Queue()
        spaces_context = SpacesContext(self.spaces, queue)
        uri_package = spaces_context.uri('package:')
        uri_tasks = self.spaces.uri('tasks:')
        uri_datastore = self.spaces.uri('datastore:')
        task_def_resource = Resource()
        httpclient_task = HTTPClientTask(self.spaces, uri_tasks.base.services.httpclienttask, task_def_resource) 
        updatemanager_task = UpdateManagerTask(self.spaces, uri_tasks.base.services.updatemanagertask, task_def_resource)
        httpclient_task.start()        
        updatemanager_task.start()
        time.sleep(1) 
        res_1 = Resource()
        res_1.url = 'file:///' + package_1_loc
        uri = spaces_context.put(uri_package.datastore, res_1)
        self.assertEqual(uri_package.datastore, uri)
        result = None
        i = 0        
        # try to find the package in the datastore. It should have a status of 'to_install'
        # since we don't have any feedback as to when the data is added, we'll just
        # continuously poll the datastore until we find it. 
        # NOTE: if UpdateManagerTask breaks and does not successfully adds the resource
        # to the datastore, then this test will wait forever. So we have made a VERY BAD
        # assumption here and put a condition to say that it should be there in 3 seconds 
        while not result and i < 3:
            try:
                result = ds.find([(uri_datastore.resource.type, uri_package.type.package),
                         (uri_package.status, 'to_install')])
            except NotFoundException:
                pass
            time.sleep(1)
            i += 1
        res_2 = Resource()
        res_2.url = 'file:///' + package_2_loc    
        uri = spaces_context.put(uri_package.datastore, res_2)
        self.assertEqual(uri_package.datastore, uri)
        result = None
        i = 0
        # make sure that the task doesn't add the same package twice to be installed, and just 
        # delete the old version of the package and replace it with the new.
        # NOTE: Again we have made a BAD ASSUMPTION here, we are giving the task 3 seconds to 
        # add the new package, and if it hasn't been done in this time, we are failing the test.
        while i < 3:
            try:
                result = ds.find([(uri_datastore.resource.type, uri_package.type.package),
                         (uri_package.status, 'to_install')])
            except NotFoundException:
                pass
            time.sleep(1)
            i += 1
        # make sure there is only 1 resource that meets the find criteria
        self.assertEqual(len(result), 1)            
        config_file_contents = open(package_2_loc, 'rb').read()
        res = result[0]
        # check the contents are of the new package
        self.assertEqual(res.bin, base64.b64encode(config_file_contents)) 
        # once the package is found, then stop the tasks.
        httpclient_task.task_stop()
        updatemanager_task.task_stop()


if __name__ == "__main__":
    #import sys;sys.argv = ['', 'Test.testName']
    unittest.main()